/*
 * Socket.cpp
 *
 *  Created on: 19/10/2013
 *      Author: RJC
 */

#include "Socket.h"

Socket::Socket() {
	WSADATA inicializador;
	if (WSAStartup(MAKEWORD(2,2), &inicializador) != 0) {
		cout << "No se puede inicializar libreria Sockets" << endl;
		exit(1);
	}

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (sock == INVALID_SOCKET) {
		cout << "Error al crear socket: " << WSAGetLastError() << endl;
		exit(1);
	}
	//bool flag = true;
	int flag = 1;
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(int));
}

Socket::Socket(SOCKET sock) {
	this->sock = sock;
	//bool flag = true;
	int flag = 1;
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(int));
}

SOCKET Socket::getSocket() {
	return sock;
}

int Socket::conectar(string ip, int puerto) {
	sockaddr_in servidor;
	servidor.sin_addr.s_addr = inet_addr(ip.c_str());
	servidor.sin_family = AF_INET;
	servidor.sin_port = htons(puerto);
	int resultado = connect(sock, (struct sockaddr*) &servidor,
			sizeof(servidor));
	return resultado;
}

int Socket::bindear(int puerto) {
	struct sockaddr_in servidor;
	servidor.sin_family = AF_INET;
	servidor.sin_addr.s_addr = INADDR_ANY;
	servidor.sin_port = htons(puerto);
	int resultado = bind(sock, (struct sockaddr*) &servidor, sizeof(servidor));
	listen(sock, 5);
	return resultado;
}

int Socket::enviar(string mensaje) {
	const char* msjChar = mensaje.c_str();
	int tamanioTotal = strlen(msjChar);
	char cadenaInt[10];
	int resultado = send(sock, itoa(tamanioTotal, cadenaInt, 10), 4, 0);
	if (resultado == SOCKET_ERROR) {
		cout << "Error al escribir: " << WSAGetLastError() << endl;
		return -1;
	} else {
		assert(resultado == 4);
	}

	int tamanioEnviado = 0;
	while (tamanioEnviado < tamanioTotal) {
		int resultado = send(sock, msjChar + tamanioEnviado * sizeof(char),
				(tamanioTotal - tamanioEnviado) * sizeof(char), 0);
		if (resultado == SOCKET_ERROR) {
			cout << "Error al escribir: " << WSAGetLastError() << endl;
			return -1;
		} else {
			tamanioEnviado += resultado;
		}
	}
	return 0;
}

int Socket::enviar(int valor) {
	char cadenaInt[10];
	itoa(valor, cadenaInt, 10);
	return enviar(string(cadenaInt));

}

string Socket::recibir() {
	char bufferTamanio[sizeof(int) + 1];
	int resultado = recv(sock, bufferTamanio, 4, 0);
	if (resultado == SOCKET_ERROR) {
		cout << "Error al recibir: " << WSAGetLastError() << endl;
		return "";
	} else {
		assert(resultado == 4);
		bufferTamanio[4] = '\0';
	}
	int tamanioARecibir = atoi(bufferTamanio);
	string respuesta = string();
	char buffer[tamanioARecibir + 1];
	int tamanioRecibido = 0;
	while (tamanioRecibido < tamanioARecibir) {
		int tamanioObtenido = recv(sock, buffer + tamanioRecibido,
				(tamanioARecibir - tamanioRecibido) * sizeof(char), 0);
		if (tamanioObtenido == SOCKET_ERROR) {
			cout << "Error al recibir: " << WSAGetLastError() << endl;
			return "";
		}
		tamanioRecibido += tamanioObtenido;
	}

	buffer[tamanioARecibir] = '\0';

	respuesta = string(buffer);
	return respuesta;
}

Socket* Socket::aceptarConexion() {
	struct sockaddr_in cliente;
	int c = sizeof(cliente);
	SOCKET nuevoSocket = accept(sock, (struct sockaddr*) &cliente, &c);
	return new Socket(nuevoSocket);
}

void Socket::cerrar() {
	closesocket(sock);
	sock = INVALID_SOCKET;
}

Socket::~Socket() {
}

